﻿Imports System
Imports System.Collections
Imports System.Collections.Generic
Imports System.Collections.ObjectModel
Imports System.Collections.Specialized
Imports System.Configuration
Imports System.Data
Imports System.Data.Common
Imports System.Diagnostics
Imports System.Globalization
Imports System.IO
Imports System.Reflection
Imports System.Runtime.CompilerServices
Imports System.Runtime.InteropServices
Imports System.Runtime.Serialization
Imports System.Runtime.Serialization.Formatters.Binary
Imports System.Text
Imports System.Timers
Imports System.Transactions
Imports System.Workflow.ComponentModel
Imports System.Workflow.ComponentModel.Serialization
Imports System.Workflow.Runtime
Imports System.Workflow.Runtime.Hosting
Imports System.Xml

Namespace System.Workflow.Runtime.Tracking
    Public NotInheritable Class SqlTrackingService
        Inherits TrackingService
        Implements IProfileNotification
        ' Events
        Public Custom Event ProfileRemoved As EventHandler([Of] ProfileRemovedEventArgs)
        Public Custom Event ProfileUpdated As EventHandler([Of] ProfileUpdatedEventArgs)

        ' Methods
        Public Sub New(ByVal parameters As NameValueCollection)
            Me._isTrans = True
            Me._defaultProfile = True
            Me._timer = New Timer
            Me._interval = 60000
            Me._types = New TypeKeyedCollection
            Me._typeCacheLock = New Object
            If (parameters Is Nothing) Then
                Throw New ArgumentNullException("parameters", ExecutionStringManager.MissingParameters)
            End If
            If (parameters.Count > 0) Then
                Dim str As String
                For Each str In parameters.Keys
                    If (String.Compare("IsTransactional", str, StringComparison.OrdinalIgnoreCase) = 0) Then
                        Me._isTrans = Boolean.Parse(parameters.Item(str))
                    Else
                        If (String.Compare("UseDefaultProfile", str, StringComparison.OrdinalIgnoreCase) = 0) Then
                            Me._defaultProfile = Boolean.Parse(parameters.Item(str))
                            [Continue] For
                        End If
                        If (String.Compare("PartitionOnCompletion", str, StringComparison.OrdinalIgnoreCase) = 0) Then
                            Me._partition = Boolean.Parse(parameters.Item(str))
                            [Continue] For
                        End If
                        If (String.Compare("ProfileChangeCheckInterval", str, StringComparison.OrdinalIgnoreCase) = 0) Then
                            Me._interval = Double.Parse(parameters.Item(str), NumberFormatInfo.InvariantInfo)
                            If (Me._interval <= 0) Then
                                Throw New ArgumentException(ExecutionStringManager.InvalidProfileCheckValue)
                            End If
                            [Continue] For
                        End If
                        If (String.Compare("ConnectionString", str, StringComparison.OrdinalIgnoreCase) = 0) Then
                            Me._unvalidatedConnectionString = parameters.Item(str)
                            [Continue] For
                        End If
                        If (String.Compare("EnableRetries", str, StringComparison.OrdinalIgnoreCase) = 0) Then
                            Me._enableRetries = Boolean.Parse(parameters.Item(str))
                            Me._ignoreCommonEnableRetries = True
                        End If
                    End If
                Next
            End If
            Me._parameters = parameters
        End Sub

        Public Sub New(ByVal connectionString As String)
            Me._isTrans = True
            Me._defaultProfile = True
            Me._timer = New Timer
            Me._interval = 60000
            Me._types = New TypeKeyedCollection
            Me._typeCacheLock = New Object
            If String.IsNullOrEmpty(connectionString) Then
                Throw New ArgumentNullException("connectionString", ExecutionStringManager.MissingConnectionString)
            End If
            Me._unvalidatedConnectionString = connectionString
        End Sub

        Private Sub CheckProfileChanges(ByVal sender As Object, ByVal e As ElapsedEventArgs)
            Dim command As DbCommand = Nothing
            Dim reader As DbDataReader = Nothing
            Try 
                Dim type As Type
                If ((Not Me.ProfileUpdated Is Nothing) OrElse (Not Me.ProfileRemoved Is Nothing)) Then
                    command = Me._dbResourceAllocator.NewCommand
                    command.CommandText = "GetUpdatedTrackingProfiles"
                    command.CommandType = CommandType.StoredProcedure
                    command.Parameters.Add(Me._dbResourceAllocator.NewDbParameter("@LastCheckDateTime", Me._lastProfileCheck))
                    Dim parameter As DbParameter = Me._dbResourceAllocator.NewDbParameter
                    parameter.ParameterName = "@MaxCheckDateTime"
                    parameter.DbType = DbType.DateTime
                    parameter.Direction = ParameterDirection.Output
                    command.Parameters.Add(parameter)
                    reader = Me.ExecuteReaderRetried(command, CommandBehavior.CloseConnection)
                    If reader.HasRows Then
                        goto Label_014E
                    End If
                End If
                Return
            Label_00AA:
                type = Nothing
                Dim s As String = Nothing
                Dim profile As TrackingProfile = Nothing
                type = Assembly.Load([TryCast](reader.Item(1),String)).GetType([TryCast](reader.Item(0),String))
                If (Not type Is Nothing) Then
                    s = [TryCast](reader.Item(2),String)
                    If (s Is Nothing) Then
                        If (Not Me.ProfileRemoved Is Nothing) Then
                            Me.ProfileRemoved.Invoke(Me, New ProfileRemovedEventArgs(type))
                        End If
                    Else
                        Dim serializer As New TrackingProfileSerializer
                        Dim reader2 As StringReader = Nothing
                        Try 
                            reader2 = New StringReader(s)
                            profile = serializer.Deserialize(reader2)
                        Finally
                            If (Not reader2 Is Nothing) Then
                                reader2.Close
                            End If
                        End Try
                        If (Not Me.ProfileUpdated Is Nothing) Then
                            Me.ProfileUpdated.Invoke(Me, New ProfileUpdatedEventArgs(type, profile))
                        End If
                    End If
                End If
            Label_014E:
                If reader.Read Then
                    goto Label_00AA
                End If
            Finally
                If ((Not reader Is Nothing) AndAlso Not reader.IsClosed) Then
                    reader.Close
                End If
                If ((Not command Is Nothing) AndAlso (Not command.Parameters.Item(1).Value Is Nothing)) Then
                    Me._lastProfileCheck = CDate(command.Parameters.Item(1).Value)
                End If
                If (((Not command Is Nothing) AndAlso (Not command.Connection Is Nothing)) AndAlso (command.Connection.State <> ConnectionState.Closed)) Then
                    command.Connection.Close
                End If
                Me._timer.Start
            End Try
        End Sub

        Friend Shared Function CreateXmlWriter(ByVal output As TextWriter) As XmlWriter
            Dim settings As New XmlWriterSettings { _
                .Indent = True, _
                .IndentChars = ChrW(9), _
                .OmitXmlDeclaration = True, _
                .CloseOutput = True _
            }
            Return XmlWriter.Create(output, settings)
        End Function

        Private Sub ExecuteNonQueryRetried(ByVal command As DbCommand)
            Dim retryCount As Short = 0
            Dim retry As New DbRetry(Me._enableRetries)
        Label_000E:
            Try 
                Me.ResetConnectionForCommand(command)
                WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, ("SqlTrackingService.ExecuteNonQueryRetried ExecuteNonQuery start: " & DateTime.UtcNow.ToString("G", CultureInfo.InvariantCulture)))
                command.ExecuteNonQuery
                WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, ("SqlTrackingService.ExecuteNonQueryRetried ExecuteNonQuery end: " & DateTime.UtcNow.ToString("G", CultureInfo.InvariantCulture)))
            Catch exception As Exception
                WorkflowTrace.Host.TraceEvent(TraceEventType.Error, 0, ("SqlTrackingService.ExecuteNonQueryRetried caught exception from ExecuteNonQuery: " & exception.ToString))
                If Not retry.TryDoRetry((retryCount)) Then
                    Throw
                End If
                WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "SqlTrackingService.ExecuteNonQueryRetried retrying.")
                goto Label_000E
            End Try
        End Sub

        Private Sub ExecuteNonQueryWithTxRetried(ByVal command As DbCommand)
            Try 
                Dim retryCount As Short = 0
                Dim retry As New DbRetry(Me._enableRetries)
            Label_000E:
                Try 
                    Me.ResetConnectionForCommand(command)
                    WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, ("SqlTrackingService.ExecuteNonQueryWithTxRetried ExecuteNonQuery start: " & DateTime.UtcNow.ToString("G", CultureInfo.InvariantCulture)))
                    command.Transaction = command.Connection.BeginTransaction
                    command.ExecuteNonQuery
                    command.Transaction.Commit
                    WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, ("SqlTrackingService.ExecuteNonQueryWithTxRetried ExecuteNonQuery end: " & DateTime.UtcNow.ToString("G", CultureInfo.InvariantCulture)))
                Catch exception As Exception
                    WorkflowTrace.Host.TraceEvent(TraceEventType.Error, 0, ("SqlTrackingService.ExecuteNonQueryWithTxRetried caught exception from ExecuteNonQuery: " & exception.ToString))
                    Try 
                        If (Not command.Transaction Is Nothing) Then
                            command.Transaction.Rollback
                        End If
                    Catch obj1 As Object
                    End Try
                    If Not retry.TryDoRetry((retryCount)) Then
                        Throw
                    End If
                    WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "SqlTrackingService.ExecuteNonQueryWithTxRetried retrying.")
                    goto Label_000E
                End Try
            Finally
                If (((Not command Is Nothing) AndAlso (Not command.Connection Is Nothing)) AndAlso (command.Connection.State <> ConnectionState.Closed)) Then
                    command.Connection.Close
                End If
            End Try
        End Sub

        Private Function ExecuteReaderRetried(ByVal command As DbCommand, ByVal behavior As CommandBehavior) As DbDataReader
            Dim reader As DbDataReader = Nothing
            Dim retryCount As Short = 0
            Dim retry As New DbRetry(Me._enableRetries)
        Label_0010:
            Try 
                Me.ResetConnectionForCommand(command)
                WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, ("SqlTrackingService.ExecuteReaderRetried ExecuteReader start: " & DateTime.UtcNow.ToString("G", CultureInfo.InvariantCulture)))
                reader = command.ExecuteReader(behavior)
                WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, ("SqlTrackingService.ExecuteReaderRetried ExecuteReader end: " & DateTime.UtcNow.ToString("G", CultureInfo.InvariantCulture)))
            Catch exception As Exception
                WorkflowTrace.Host.TraceEvent(TraceEventType.Error, 0, ("SqlTrackingService.ExecuteReaderRetried caught exception from ExecuteReader: " & exception.ToString))
                If Not retry.TryDoRetry((retryCount)) Then
                    Throw
                End If
                WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "SqlTrackingService.ExecuteReaderRetried retrying.")
                goto Label_0010
            End Try
            Return reader
        End Function

        Private Sub ExecuteRetried(ByVal executeRetried As ExecuteRetriedDelegate, ByVal param As Object)
            Dim retryCount As Short = 0
            Dim retry As New DbRetry(Me._enableRetries)
        Label_000E:
            Try 
                WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, ("SqlTrackingService.ExecuteRetried " & executeRetried.Method.Name & " start: " & DateTime.UtcNow.ToString("G", CultureInfo.InvariantCulture)))
                executeRetried.Invoke(param)
                WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, ("SqlTrackingService.ExecuteRetried " & executeRetried.Method.Name & " end: " & DateTime.UtcNow.ToString("G", CultureInfo.InvariantCulture)))
            Catch exception As Exception
                WorkflowTrace.Host.TraceEvent(TraceEventType.Error, 0, ("SqlTrackingService.ExecuteRetried caught exception: " & exception.ToString))
                If Not retry.TryDoRetry((retryCount)) Then
                    Throw
                End If
                WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, ("SqlTrackingService.ExecuteRetried " & executeRetried.Method.Name & " retrying."))
                goto Label_000E
            End Try
        End Sub

        Protected Friend Overrides Function GetProfile(ByVal scheduleInstanceId As Guid) As TrackingProfile
            Dim profile As TrackingProfile = Nothing
            Me.GetProfile(scheduleInstanceId, profile)
            Return profile
        End Function

        Private Function GetProfile(ByVal scheduleInstanceId As Guid, <Out> ByRef profile As TrackingProfile) As Boolean
            Dim flag As Boolean
            profile = Nothing
            Dim command As DbCommand = Me._dbResourceAllocator.NewCommand
            command.CommandType = CommandType.StoredProcedure
            command.CommandText = "[dbo].[GetInstanceTrackingProfile]"
            command.Parameters.Add(Me._dbResourceAllocator.NewDbParameter("@InstanceId", scheduleInstanceId))
            Dim reader As DbDataReader = Nothing
            Try 
                reader = Me.ExecuteReaderRetried(command, CommandBehavior.CloseConnection)
                If Not reader.HasRows Then
                    reader.Close
                    profile = Nothing
                    Return False
                End If
                If Not reader.Read Then
                    reader.Close
                    profile = Nothing
                    Return False
                End If
                If reader.IsDBNull(0) Then
                    profile = Nothing
                Else
                    Dim s As String = reader.GetString(0)
                    Dim serializer As New TrackingProfileSerializer
                    Dim reader2 As StringReader = Nothing
                    Try 
                        reader2 = New StringReader(s)
                        profile = serializer.Deserialize(reader2)
                    Finally
                        If (Not reader2 Is Nothing) Then
                            reader2.Close
                        End If
                    End Try
                End If
                flag = True
            Finally
                If ((Not reader Is Nothing) AndAlso Not reader.IsClosed) Then
                    reader.Close
                End If
                If (((Not command Is Nothing) AndAlso (Not command.Connection Is Nothing)) AndAlso (command.Connection.State <> ConnectionState.Closed)) Then
                    command.Connection.Close
                End If
            End Try
            Return flag
        End Function

        Protected Friend Overrides Function GetProfile(ByVal workflowType As Type, ByVal profileVersion As Version) As TrackingProfile
            If (workflowType Is Nothing) Then
                Throw New ArgumentNullException("workflowType")
            End If
            Return Me.GetProfileByScheduleType(workflowType, profileVersion, False)
        End Function

        Private Function GetProfileByScheduleType(ByVal workflowType As Type, ByVal profileVersionId As Version, ByVal wantToCreateDefault As Boolean) As TrackingProfile
            Dim command As DbCommand = Me._dbResourceAllocator.NewCommand
            Dim reader As DbDataReader = Nothing
            Dim profile As TrackingProfile = Nothing
            command.CommandType = CommandType.StoredProcedure
            command.CommandText = "dbo.GetTrackingProfile"
            command.Parameters.Add(Me._dbResourceAllocator.NewDbParameter("@TypeFullName", workflowType.FullName))
            command.Parameters.Add(Me._dbResourceAllocator.NewDbParameter("@AssemblyFullName", workflowType.Assembly.FullName))
            If (Not profileVersionId Is SqlTrackingService.UnknownProfileVersionId) Then
                command.Parameters.Add(Me._dbResourceAllocator.NewDbParameter("@Version", profileVersionId.ToString))
            End If
            command.Parameters.Add(Me._dbResourceAllocator.NewDbParameter("@CreateDefault", wantToCreateDefault))
            Try 
                reader = Me.ExecuteReaderRetried(command, CommandBehavior.CloseConnection)
                If Not reader.Read Then
                    Return profile
                End If
                Dim s As String = [TryCast](reader.Item(0),String)
                If (s Is Nothing) Then
                    Return profile
                End If
                Dim serializer As New TrackingProfileSerializer
                Dim reader2 As StringReader = Nothing
                Try 
                    reader2 = New StringReader(s)
                    profile = serializer.Deserialize(reader2)
                Finally
                    If (Not reader2 Is Nothing) Then
                        reader2.Close
                    End If
                End Try
            Finally
                If ((Not reader Is Nothing) AndAlso Not reader.IsClosed) Then
                    reader.Close
                End If
                If (((Not command Is Nothing) AndAlso (Not command.Connection Is Nothing)) AndAlso (command.Connection.State <> ConnectionState.Closed)) Then
                    command.Connection.Close
                End If
            End Try
            Return profile
        End Function

        Protected Friend Overrides Function GetTrackingChannel(ByVal parameters As TrackingParameters) As TrackingChannel
            If (parameters Is Nothing) Then
                Throw New ArgumentNullException("parameters")
            End If
            Return New SqlTrackingChannel(parameters, Me)
        End Function

        Private Sub ResetConnectionForCommand(ByVal command As DbCommand)
            If ((Not command Is Nothing) AndAlso ((Not command.Connection Is Nothing) AndAlso (ConnectionState.Open <> command.Connection.State))) Then
                If (command.Connection.State <> ConnectionState.Closed) Then
                    command.Connection.Close
                End If
                command.Connection.Dispose
                command.Connection = Me._dbResourceAllocator.OpenNewConnectionNoEnlist
            End If
        End Sub

        Protected Friend Overrides Sub Start()
            Me._lastProfileCheck = DateTime.UtcNow
            Me._dbResourceAllocator = New DbResourceAllocator(MyBase.Runtime, Me._parameters, Me._unvalidatedConnectionString)
            Me._transactionService = MyBase.Runtime.GetService([Of] WorkflowCommitWorkBatchService)
            Me._dbResourceAllocator.DetectSharedConnectionConflict(Me._transactionService)
            If (Not Me._ignoreCommonEnableRetries AndAlso (Not MyBase.Runtime Is Nothing)) Then
                Dim commonParameters As NameValueConfigurationCollection = MyBase.Runtime.CommonParameters
                If (Not commonParameters Is Nothing) Then
                    Dim str As String
                    For Each str In commonParameters.AllKeys
                        If (String.Compare("EnableRetries", str, StringComparison.OrdinalIgnoreCase) = 0) Then
                            Me._enableRetries = Boolean.Parse(commonParameters.Item(str).Value)
                            Exit For
                        End If
                    Next
                End If
            End If
            Me._timer.Interval = Me._interval
            Me._timer.AutoReset = False
            AddHandler Me._timer.Elapsed, New ElapsedEventHandler(AddressOf Me.CheckProfileChanges)
            Me._timer.Start
            MyBase.Start
        End Sub

        Protected Friend Overrides Function TryGetProfile(ByVal workflowType As Type, <Out> ByRef profile As TrackingProfile) As Boolean
            If (workflowType Is Nothing) Then
                Throw New ArgumentNullException("workflowType")
            End If
            profile = Me.GetProfileByScheduleType(workflowType, SqlTrackingService.UnknownProfileVersionId, Me._defaultProfile)
            If (profile Is Nothing) Then
                Return False
            End If
            Return True
        End Function

        Protected Friend Overrides Function TryReloadProfile(ByVal workflowType As Type, ByVal scheduleInstanceId As Guid, <Out> ByRef profile As TrackingProfile) As Boolean
            If (workflowType Is Nothing) Then
                Throw New ArgumentNullException("workflowType")
            End If
            If Me.GetProfile(scheduleInstanceId, profile) Then
                Return True
            End If
            profile = Nothing
            Return False
        End Function


        ' Properties
        Public ReadOnly Property ConnectionString As String
            Get
                Return Me._unvalidatedConnectionString
            End Get
        End Property

        Friend ReadOnly Property DbResourceAllocator As DbResourceAllocator
            Get
                Return Me._dbResourceAllocator
            End Get
        End Property

        Public Property EnableRetries As Boolean
            Get
                Return Me._enableRetries
            End Get
            Set(ByVal value As Boolean)
                Me._enableRetries = value
                Me._ignoreCommonEnableRetries = True
            End Set
        End Property

        Public Property IsTransactional As Boolean
            Get
                Return Me._isTrans
            End Get
            Set(ByVal value As Boolean)
                Me._isTrans = value
            End Set
        End Property

        Public Property PartitionOnCompletion As Boolean
            Get
                Return Me._partition
            End Get
            Set(ByVal value As Boolean)
                Me._partition = value
            End Set
        End Property

        Public Property ProfileChangeCheckInterval As Double
            Get
                Return Me._interval
            End Get
            Set(ByVal value As Double)
                If (value <= 0) Then
                    Throw New ArgumentException(ExecutionStringManager.InvalidProfileCheckValue)
                End If
                Me._interval = value
                Me._timer.Interval = Me._interval
            End Set
        End Property

        Public Property UseDefaultProfile As Boolean
            Get
                Return Me._defaultProfile
            End Get
            Set(ByVal value As Boolean)
                Me._defaultProfile = value
            End Set
        End Property


        ' Fields
        Private _dbResourceAllocator As DbResourceAllocator
        Private _defaultProfile As Boolean
        Private _enableRetries As Boolean
        Private _ignoreCommonEnableRetries As Boolean
        Private _interval As Double
        Private _isTrans As Boolean
        Private _lastProfileCheck As DateTime
        Private _parameters As NameValueCollection
        Private _partition As Boolean
        Private _timer As Timer
        Private _transactionService As WorkflowCommitWorkBatchService
        Private _typeCacheLock As Object
        Private _types As TypeKeyedCollection
        Private _unvalidatedConnectionString As String
        Private Shared UnknownProfileVersionId As Version = New Version(0, 0)

        ' Nested Types
        <StructLayout(LayoutKind.Sequential)> _
        Private Structure AddedActivity
            Public ActivityTypeFullName As String
            Public ActivityTypeAssemblyFullName As String
            Public QualifiedName As String
            Public ParentQualifiedName As String
            Public AddedActivityActionXoml As String
            Public Order As Integer
        End Structure

        Private Delegate Sub ExecuteRetriedDelegate(ByVal param As Object)

        <StructLayout(LayoutKind.Sequential)> _
        Private Structure RemovedActivity
            Public QualifiedName As String
            Public ParentQualifiedName As String
            Public RemovedActivityActionXoml As String
            Public Order As Integer
        End Structure

        Private Class SerializedDataItem
            Inherits TrackingDataItem
            ' Fields
            Public NonSerializable As Boolean
            Public SerializedData As Byte()
            Public StringData As String
            Public Type As Type
        End Class

        Private Class SerializedEventArgs
            Inherits EventArgs
            ' Fields
            Public SerializedArgs As Byte()
            Public Type As Type
        End Class

        Private Class SerializedWorkflowChangedEventArgs
            Inherits SerializedEventArgs
            ' Fields
            Public AddedActivities As IList([Of] AddedActivity) = New List([Of] AddedActivity)
            Public RemovedActivities As IList([Of] RemovedActivity) = New List([Of] RemovedActivity)
        End Class

        Friend Class SqlTrackingChannel
            Inherits TrackingChannel
            Implements IPendingWork
            ' Methods
            Protected Sub New()
                Me._internalId = -1
                Me._tmpInternalId = -1
                Me._activityInstanceId = New Dictionary([Of] String, Long)(&H20)
                Me._tmpActivityInstanceId = New Dictionary([Of] String, Long)(10)
            End Sub

            Public Sub New(ByVal parameters As TrackingParameters, ByVal service As SqlTrackingService)
                Me._internalId = -1
                Me._tmpInternalId = -1
                Me._activityInstanceId = New Dictionary([Of] String, Long)(&H20)
                Me._tmpActivityInstanceId = New Dictionary([Of] String, Long)(10)
                If (Not service Is Nothing) Then
                    Me._service = service
                    Me._parameters = parameters
                    Me._isTrans = service.IsTransactional
                    Me.GetCallPathKeys(parameters.CallPath)
                    If Not Me._isTrans Then
                        Me._service.ExecuteRetried(New ExecuteRetriedDelegate(AddressOf Me.ExecuteInsertWorkflowInstance), Nothing)
                    End If
                End If
            End Sub

            Private Sub AddAddedActivity(ByVal added As Activity, ByVal activities As IList([Of] AddedActivity))
                Dim item As New AddedActivity { _
                    .Order = -1 _
                }
                Dim type As Type = added.GetType
                item.ActivityTypeFullName = type.FullName
                item.ActivityTypeAssemblyFullName = type.Assembly.FullName
                item.QualifiedName = added.QualifiedName
                If (Not added.Parent Is Nothing) Then
                    item.ParentQualifiedName = added.Parent.QualifiedName
                End If
                activities.Add(item)
                If TypeOf added Is CompositeActivity Then
                    Dim activity2 As Activity
                    For Each activity2 In DirectCast(added, CompositeActivity).Activities
                        Me.AddAddedActivity(activity2, activities)
                    Next
                End If
            End Sub

            Private Sub AddAddedActivity(ByVal addedAction As AddedActivityAction, ByVal order As Integer, ByVal activities As IList([Of] AddedActivity))
                Dim addedActivity As Activity = addedAction.AddedActivity
                Dim item As New AddedActivity { _
                    .Order = order _
                }
                Dim type As Type = addedActivity.GetType
                item.ActivityTypeFullName = type.FullName
                item.ActivityTypeAssemblyFullName = type.Assembly.FullName
                item.QualifiedName = addedActivity.QualifiedName
                If (Not addedActivity.Parent Is Nothing) Then
                    item.ParentQualifiedName = addedActivity.Parent.QualifiedName
                End If
                item.AddedActivityActionXoml = Me.GetXomlDocument(addedAction)
                activities.Add(item)
                If TypeOf addedActivity Is CompositeActivity Then
                    Dim activity3 As Activity
                    For Each activity3 In DirectCast(addedActivity, CompositeActivity).Activities
                        Me.AddAddedActivity(activity3, activities)
                    Next
                End If
            End Sub

            Private Sub AddRemovedActivity(ByVal removed As Activity, ByVal activities As IList([Of] RemovedActivity))
                Dim item As New RemovedActivity { _
                    .Order = -1, _
                    .QualifiedName = removed.QualifiedName _
                }
                If (Not removed.Parent Is Nothing) Then
                    item.ParentQualifiedName = removed.Parent.QualifiedName
                End If
                activities.Add(item)
                If TypeOf removed Is CompositeActivity Then
                    Dim activity2 As Activity
                    For Each activity2 In DirectCast(removed, CompositeActivity).Activities
                        Me.AddRemovedActivity(activity2, activities)
                    Next
                End If
            End Sub

            Private Sub AddRemovedActivity(ByVal removedAction As RemovedActivityAction, ByVal order As Integer, ByVal activities As IList([Of] RemovedActivity))
                Dim originalRemovedActivity As Activity = removedAction.OriginalRemovedActivity
                Dim item As New RemovedActivity { _
                    .Order = order, _
                    .QualifiedName = originalRemovedActivity.QualifiedName _
                }
                If (Not originalRemovedActivity.Parent Is Nothing) Then
                    item.ParentQualifiedName = originalRemovedActivity.Parent.QualifiedName
                End If
                item.RemovedActivityActionXoml = Me.GetXomlDocument(removedAction)
                activities.Add(item)
                If TypeOf originalRemovedActivity Is CompositeActivity Then
                    Dim activity3 As Activity
                    For Each activity3 In DirectCast(originalRemovedActivity, CompositeActivity).Activities
                        Me.AddRemovedActivity(activity3, activities)
                    Next
                End If
            End Sub

            Private Sub BatchExecuteInsertEventAnnotation(ByVal internalId As Long, ByVal eventTypeId As Char, ByVal annotations As IList([Of] KeyValuePair([Of] Long, String)), ByVal command As DbCommand)
                If ((Not annotations Is Nothing) AndAlso (annotations.Count > 0)) Then
                    If (annotations.Count <= SqlTrackingChannel._eventAnnotationBatchSize) Then
                        Me.ExecuteInsertEventAnnotation(internalId, eventTypeId, annotations, command)
                    Else
                        Dim list As New List([Of] KeyValuePair([Of] Long, String))(SqlTrackingChannel._eventAnnotationBatchSize)
                        Dim pair As KeyValuePair([Of] Long, String)
                        For Each pair In annotations
                            list.Add(pair)
                            If (list.Count = SqlTrackingChannel._eventAnnotationBatchSize) Then
                                Me.ExecuteInsertEventAnnotation(internalId, eventTypeId, list, command)
                                list.Clear
                            End If
                        Next
                        If (list.Count > 0) Then
                            Me.ExecuteInsertEventAnnotation(internalId, eventTypeId, list, command)
                        End If
                    End If
                End If
            End Sub

            Private Sub BatchExecuteInsertTrackingDataItems(ByVal internalId As Long, ByVal eventTypeId As Char, ByVal items As IList([Of] KeyValuePair([Of] Long, TrackingDataItem)), ByVal command As DbCommand)
                If ((Not items Is Nothing) AndAlso (items.Count > 0)) Then
                    If (items.Count <= SqlTrackingChannel._dataItemBatchSize) Then
                        Me.ExecuteInsertTrackingDataItems(internalId, eventTypeId, items, command)
                    Else
                        Dim list As New List([Of] KeyValuePair([Of] Long, TrackingDataItem))(SqlTrackingChannel._dataItemBatchSize)
                        Dim pair As KeyValuePair([Of] Long, TrackingDataItem)
                        For Each pair In items
                            list.Add(pair)
                            If (list.Count = SqlTrackingChannel._dataItemBatchSize) Then
                                Me.ExecuteInsertTrackingDataItems(internalId, eventTypeId, list, command)
                                list.Clear
                            End If
                        Next
                        If (list.Count > 0) Then
                            Me.ExecuteInsertTrackingDataItems(internalId, eventTypeId, list, command)
                        End If
                    End If
                End If
            End Sub

            Private Sub BuildInsertActivityStatusEventParameters(ByVal internalId As Long, ByVal activityInstanceId As Long, ByVal parameterId As Integer, ByVal record As ActivityTrackingRecord, ByVal command As DbCommand)
                Dim str As String = parameterId.ToString(CultureInfo.InvariantCulture)
                Dim parameter As DbParameter = Me.DbResourceAllocator.NewDbParameter(("@ActivityInstanceId" & str), DbType.Int64, ParameterDirection.InputOutput)
                command.Parameters.Add(parameter)
                If (activityInstanceId > 0) Then
                    parameter.Value = activityInstanceId
                End If
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter(("@QualifiedName" & str), record.QualifiedName))
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter(("@ContextGuid" & str), record.ContextGuid))
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter(("@ParentContextGuid" & str), record.ParentContextGuid))
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter(("@ExecutionStatusId" & str), CInt(record.ExecutionStatus)))
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter(("@EventDateTime" & str), record.EventDateTime))
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter(("@EventOrder" & str), record.EventOrder))
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter(("@ActivityExecutionStatusEventId" & str), DbType.Int64, ParameterDirection.Output))
            End Sub

            Private Sub BuildInsertUserEventParameters(ByVal internalId As Long, ByVal activityInstanceId As Long, ByVal record As UserTrackingRecord, ByVal command As DbCommand)
                command.CommandType = CommandType.StoredProcedure
                command.CommandText = "[dbo].[InsertUserEvent]"
                command.Parameters.Clear
                Dim parameter As DbParameter = Me.DbResourceAllocator.NewDbParameter("@WorkflowInstanceInternalId", DbType.Int64)
                command.Parameters.Add(parameter)
                parameter.Value = internalId
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@EventOrder", record.EventOrder))
                parameter = Me.DbResourceAllocator.NewDbParameter("@ActivityInstanceId", DbType.Int64, ParameterDirection.InputOutput)
                command.Parameters.Add(parameter)
                If (activityInstanceId > 0) Then
                    parameter.Value = activityInstanceId
                Else
                    command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@QualifiedName", record.QualifiedName))
                    command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@ContextGuid", record.ContextGuid))
                    command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@ParentContextGuid", record.ParentContextGuid))
                End If
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@EventDateTime", record.EventDateTime))
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@UserDataKey", record.UserDataKey))
                If (Not record.UserData Is Nothing) Then
                    Dim type As Type = record.UserData.GetType
                    Dim state As Byte() = Nothing
                    Dim nonSerializable As Boolean = False
                    Dim stringData As String = Nothing
                    If Not TypeOf record.UserData Is SerializedDataItem Then
                        Me.SerializeDataItem(record.UserData, state, nonSerializable)
                    End If
                    Dim userData As SerializedDataItem = [TryCast](record.UserData,SerializedDataItem)
                    state = userData.SerializedData
                    nonSerializable = userData.NonSerializable
                    stringData = userData.StringData
                    command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@UserDataTypeFullName", type.FullName))
                    command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@UserDataAssemblyFullName", type.Assembly.FullName))
                    command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@UserData_Str", stringData))
                    command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@UserData_Blob", state))
                    command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@UserDataNonSerializable", nonSerializable))
                End If
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@UserEventId", DbType.Int64, ParameterDirection.Output))
            End Sub

            Private Sub BuildInsertWorkflowInstanceEventParameters(ByVal internalId As Long, ByVal record1 As WorkflowTrackingRecord, ByVal record2 As WorkflowTrackingRecord, ByVal command As DbCommand)
                If (record1 Is Nothing) Then
                    Throw New ArgumentNullException("record")
                End If
                If (command Is Nothing) Then
                    Throw New ArgumentNullException("command")
                End If
                command.CommandType = CommandType.StoredProcedure
                command.CommandText = "[dbo].[InsertWorkflowInstanceEvent]"
                command.Parameters.Clear
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@WorkflowInstanceInternalId", internalId))
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@TrackingWorkflowEventId1", CInt(record1.TrackingWorkflowEvent)))
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@EventDateTime1", record1.EventDateTime))
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@EventOrder1", record1.EventOrder))
                If (Not record1.EventArgs Is Nothing) Then
                    Dim type As Type = record1.EventArgs.GetType
                    Dim serializedArgs As Byte() = Nothing
                    If Not TypeOf record1.EventArgs Is SerializedEventArgs Then
                        record1 = Me.SerializeRecord(record1)
                    End If
                    Dim eventArgs As SerializedEventArgs = [TryCast](record1.EventArgs,SerializedEventArgs)
                    serializedArgs = eventArgs.SerializedArgs
                    command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@EventArgTypeFullName1", type.FullName))
                    command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@EventArgAssemblyFullName1", type.Assembly.FullName))
                    command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@EventArg1", serializedArgs))
                End If
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@WorkflowInstanceEventId1", DbType.Int64, ParameterDirection.Output))
                If (Not record2 Is Nothing) Then
                    command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@TrackingWorkflowEventId2", CInt(record2.TrackingWorkflowEvent)))
                    command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@EventDateTime2", record2.EventDateTime))
                    command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@EventOrder2", record2.EventOrder))
                    If (Not record2.EventArgs Is Nothing) Then
                        Dim type2 As Type = record2.EventArgs.GetType
                        Dim buffer2 As Byte() = Nothing
                        If Not TypeOf record2.EventArgs Is SerializedEventArgs Then
                            record2 = Me.SerializeRecord(record2)
                        End If
                        Dim args2 As SerializedEventArgs = [TryCast](record2.EventArgs,SerializedEventArgs)
                        buffer2 = args2.SerializedArgs
                        command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@EventArgTypeFullName2", type2.FullName))
                        command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@EventArgAssemblyFullName2", type2.Assembly.FullName))
                        command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@EventArg2", buffer2))
                    End If
                    command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@WorkflowInstanceEventId2", DbType.Int64, ParameterDirection.Output))
                End If
            End Sub

            Private Sub BuildInsertWorkflowInstanceParameters(ByVal command As DbCommand)
                command.CommandType = CommandType.StoredProcedure
                command.CommandText = "[dbo].[InsertWorkflowInstance]"
                command.Parameters.Clear
                Dim flag As Boolean = False
                Dim str As String = [TryCast](Me._parameters.RootActivity.GetValue(Activity.WorkflowXamlMarkupProperty),String)
                If ((Not str Is Nothing) AndAlso (str.Length > 0)) Then
                    flag = True
                End If
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@WorkflowInstanceId", Me._parameters.InstanceId))
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@TypeFullName", If(flag, Me._parameters.InstanceId.ToString, Me._parameters.WorkflowType.FullName)))
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@AssemblyFullName", If(flag, Me._parameters.InstanceId.ToString, Me._parameters.WorkflowType.Assembly.FullName)))
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@ContextGuid", Me._parameters.ContextGuid))
                If (Guid.Empty <> Me._parameters.CallerInstanceId) Then
                    command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@CallerInstanceId", Me._parameters.CallerInstanceId))
                    command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@CallPath", Me._callPathKey))
                    command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@CallerContextGuid", Me._parameters.CallerContextGuid))
                    command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@CallerParentContextGuid", Me._parameters.CallerParentContextGuid))
                End If
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@EventDateTime", Me.GetSqlDateTimeString(DateTime.UtcNow)))
            End Sub

            Private Function BuildQualifiedNameVarName(ByVal qId As String, ByVal context As Guid, ByVal parentContext As Guid) As String
                Dim guid As Guid = HashHelper.HashServiceType(qId)
                Return String.Concat(New String() { guid.ToString.Replace("-"c, "_"c), "_", context.ToString.Replace("-"c, "_"c), "_", parentContext.ToString.Replace("-"c, "_"c) })
            End Function

            Public Sub Commit(ByVal transaction As Transaction, ByVal items As ICollection)
                If ((Not items Is Nothing) AndAlso (items.Count <> 0)) Then
                    Dim command As DbCommand = Nothing
                    Dim dbConnection As DbConnection = Nothing
                    Dim isNewConnection As Boolean = False
                    Dim localTransaction As DbTransaction = Nothing
                    Dim flag2 As Boolean = False
                    Try 
                        dbConnection = Me.DbResourceAllocator.GetEnlistedConnection(Me.WorkflowCommitWorkBatchService, transaction, isNewConnection)
                        localTransaction = DbResourceAllocator.GetLocalTransaction(Me.WorkflowCommitWorkBatchService, transaction)
                        If (localTransaction Is Nothing) Then
                            localTransaction = dbConnection.BeginTransaction(IsolationLevel.ReadCommitted)
                            flag2 = True
                        End If
                        command = DbResourceAllocator.NewCommand(dbConnection)
                        command.Transaction = localTransaction
                        Dim internalId As Long = -1
                        If (Me._internalId <= 0) Then
                            Me.ExecuteInsertWorkflowInstance(command)
                            internalId = Me._tmpInternalId
                        Else
                            internalId = Me._internalId
                        End If
                        Dim activities As IList([Of] ActivityTrackingRecord) = New List([Of] ActivityTrackingRecord)(5)
                        Dim record As WorkflowTrackingRecord = Nothing
                        Dim obj2 As Object
                        For Each obj2 In items
                            If Not TypeOf obj2 Is TrackingRecord Then
                                [Continue] For
                            End If
                            If TypeOf obj2 Is ActivityTrackingRecord Then
                                If (Not record Is Nothing) Then
                                    Me.ExecuteInsertWorkflowInstanceEvent(internalId, record, Nothing, command)
                                    record = Nothing
                                End If
                                Dim item As ActivityTrackingRecord = DirectCast(obj2, ActivityTrackingRecord)
                                activities.Add(item)
                                If (SqlTrackingChannel._activityEventBatchSize = activities.Count) Then
                                    Me.ExecuteInsertActivityStatusInstance(internalId, activities, command)
                                    activities = New List([Of] ActivityTrackingRecord)(5)
                                End If
                                [Continue] For
                            End If
                            If TypeOf obj2 Is UserTrackingRecord Then
                                If (activities.Count > 0) Then
                                    Me.ExecuteInsertActivityStatusInstance(internalId, activities, command)
                                    activities.Clear
                                End If
                                If (Not record Is Nothing) Then
                                    Me.ExecuteInsertWorkflowInstanceEvent(internalId, record, Nothing, command)
                                    record = Nothing
                                End If
                                Me.ExecuteInsertUserEvent(internalId, DirectCast(obj2, UserTrackingRecord), command)
                                [Continue] For
                            End If
                            If TypeOf obj2 Is WorkflowTrackingRecord Then
                                If (activities.Count > 0) Then
                                    Me.ExecuteInsertActivityStatusInstance(internalId, activities, command)
                                    activities.Clear
                                End If
                                Dim record3 As WorkflowTrackingRecord = DirectCast(obj2, WorkflowTrackingRecord)
                                If (TrackingWorkflowEvent.Changed = record3.TrackingWorkflowEvent) Then
                                    If (Not record Is Nothing) Then
                                        Me.ExecuteInsertWorkflowInstanceEvent(internalId, record, Nothing, command)
                                        record = Nothing
                                    End If
                                    Me.ExecuteInsertWorkflowChange(internalId, record3, command)
                                    [Continue] For
                                End If
                                If (Not record Is Nothing) Then
                                    Me.ExecuteInsertWorkflowInstanceEvent(internalId, record, record3, command)
                                    record = Nothing
                                Else
                                    record = record3
                                End If
                            End If
                        Next
                        If (activities.Count > 0) Then
                            Me.ExecuteInsertActivityStatusInstance(internalId, activities, command)
                        End If
                        If (Not record Is Nothing) Then
                            Me.ExecuteInsertWorkflowInstanceEvent(internalId, record, Nothing, command)
                            record = Nothing
                        End If
                        If Me._completedTerminated Then
                            Me.ExecuteSetEndDate(internalId, command)
                        End If
                        If flag2 Then
                            localTransaction.Commit
                        End If
                    Catch exception As DbException
                        If flag2 Then
                            localTransaction.Rollback
                        End If
                        WorkflowTrace.Host.TraceEvent(TraceEventType.Error, 0, ("Error writing tracking data to database: " & exception))
                        Throw
                    Finally
                        If isNewConnection Then
                            dbConnection.Dispose
                        End If
                    End Try
                End If
            End Sub

            Public Sub Complete(ByVal succeeded As Boolean, ByVal items As ICollection)
                If Not succeeded Then
                    Me._completedTerminated = False
                    Me._pendingArchive = False
                    Me._tmpInternalId = -1
                    Me._tmpActivityInstanceId.Clear
                Else
                    If ((-1 = Me._internalId) AndAlso (Me._tmpInternalId > 0)) Then
                        Me._internalId = Me._tmpInternalId
                    End If
                    If ((Not Me._tmpActivityInstanceId Is Nothing) AndAlso (Me._tmpActivityInstanceId.Count > 0)) Then
                        Dim str As String
                        For Each str In Me._tmpActivityInstanceId.Keys
                            If Not Me._activityInstanceId.ContainsKey(str) Then
                                Me._activityInstanceId.Add(str, Me._tmpActivityInstanceId.Item(str))
                            End If
                        Next
                        Me._tmpActivityInstanceId.Clear
                    End If
                    If Me._pendingArchive Then
                        Try 
                            Me._service.ExecuteRetried(New ExecuteRetriedDelegate(AddressOf Me.PartitionInstance), Nothing)
                        Catch exception As Exception
                            WorkflowTrace.Host.TraceEvent(TraceEventType.Error, 0, String.Format(CultureInfo.InvariantCulture, "Error partitioning instance {0}: {1}", New Object() { Me._parameters.InstanceId, exception.ToString }))
                        End Try
                    End If
                End If
            End Sub

            Private Sub ExecuteInsertActivityStatusInstance(ByVal param As Object)
                Dim record As ActivityTrackingRecord = [TryCast](param,ActivityTrackingRecord)
                If (record Is Nothing) Then
                    Throw New ArgumentException(ExecutionStringManager.InvalidActivityTrackingRecordParameter, "param")
                End If
                Dim connection As DbConnection = Me.DbResourceAllocator.OpenNewConnection
                Dim transaction As DbTransaction = Nothing
                Try 
                    transaction = connection.BeginTransaction(IsolationLevel.ReadCommitted)
                    Dim command As DbCommand = connection.CreateCommand
                    command.Transaction = transaction
                    Dim activities As IList([Of] ActivityTrackingRecord) = New List([Of] ActivityTrackingRecord)(1) { record }
                    Me.ExecuteInsertActivityStatusInstance(Me._internalId, activities, command)
                    transaction.Commit
                Catch exception1 As Exception
                    Try 
                        If (Not transaction Is Nothing) Then
                            transaction.Rollback
                        End If
                    Catch exception2 As Exception
                    End Try
                    Throw
                Finally
                    If ((Not connection Is Nothing) AndAlso (connection.State <> ConnectionState.Closed)) Then
                        connection.Close
                    End If
                End Try
            End Sub

            Private Sub ExecuteInsertActivityStatusInstance(ByVal internalId As Long, ByVal activities As IList([Of] ActivityTrackingRecord), ByVal command As DbCommand)
                If ((Not activities Is Nothing) AndAlso (activities.Count > 0)) Then
                    If (activities.Count > SqlTrackingChannel._activityEventBatchSize) Then
                        Throw New ArgumentOutOfRangeException("activities")
                    End If
                    If (((command Is Nothing) OrElse (command.Connection Is Nothing)) OrElse (ConnectionState.Open <> command.Connection.State)) Then
                        Throw New ArgumentException
                    End If
                    command.CommandType = CommandType.StoredProcedure
                    command.CommandText = "[dbo].[InsertActivityExecutionStatusEventMultiple]"
                    command.Parameters.Clear
                    command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@WorkflowInstanceId", Me._parameters.InstanceId))
                    Dim parameter As DbParameter = Me.DbResourceAllocator.NewDbParameter("@WorkflowInstanceInternalId", DbType.Int64, ParameterDirection.InputOutput)
                    command.Parameters.Add(parameter)
                    If (internalId > 0) Then
                        parameter.Value = internalId
                    End If
                    command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@WorkflowInstanceContextGuid", Me._parameters.ContextGuid))
                    Dim strArray As String() = New String(5  - 1) {}
                    Dim i As Integer
                    For i = 0 To activities.Count - 1
                        Dim record As ActivityTrackingRecord = activities.Item(i)
                        Dim id As Long = -1
                        strArray(i) = Me.BuildQualifiedNameVarName(record.QualifiedName, record.ContextGuid, record.ParentContextGuid)
                        Me.TryGetActivityInstanceId(strArray(i), id)
                        Me.BuildInsertActivityStatusEventParameters(internalId, id, (i + 1), record, command)
                    Next i
                    command.ExecuteNonQuery
                    Dim numArray As Long() = New Long() { -1, -1, -1, -1, -1 }
                    Dim j As Integer
                    For j = 0 To activities.Count - 1
                        Dim str As String = (j + 1).ToString(CultureInfo.InvariantCulture)
                        Dim num4 As Long = CLng(command.Parameters.Item(("@ActivityInstanceId" & str)).Value)
                        If (ActivityExecutionStatus.Closed <> activities.Item(j).ExecutionStatus) Then
                            Me.SetActivityInstanceId(strArray(j), num4)
                        Else
                            Me.RemoveActivityInstanceId(strArray(j))
                        End If
                        numArray(j) = CLng(command.Parameters.Item(("@ActivityExecutionStatusEventId" & str)).Value)
                    Next j
                    Dim annotations As New List([Of] KeyValuePair([Of] Long, String))(10)
                    Dim items As New List([Of] KeyValuePair([Of] Long, TrackingDataItem))(10)
                    Dim k As Integer
                    For k = 0 To activities.Count - 1
                        Dim record2 As ActivityTrackingRecord = activities.Item(k)
                        Dim key As Long = numArray(k)
                        If (key <= 0) Then
                            Throw New InvalidOperationException
                        End If
                        Dim str2 As String
                        For Each str2 In record2.Annotations
                            annotations.Add(New KeyValuePair([Of] Long, String)(key, str2))
                        Next
                        Dim item As TrackingDataItem
                        For Each item In record2.Body
                            items.Add(New KeyValuePair([Of] Long, TrackingDataItem)(key, item))
                        Next
                    Next k
                    Me.BatchExecuteInsertEventAnnotation(internalId, "a"c, annotations, command)
                    Me.BatchExecuteInsertTrackingDataItems(internalId, "a"c, items, command)
                End If
            End Sub

            Private Sub ExecuteInsertAddedActivity(ByVal internalId As Long, ByVal qualifiedName As String, ByVal parentQualifiedName As String, ByVal typeFullName As String, ByVal assemblyFullName As String, ByVal addedActivityActionXoml As String, ByVal eventId As Long, ByVal order As Integer, ByVal command As DbCommand)
                If (((command Is Nothing) OrElse (command.Connection Is Nothing)) OrElse (ConnectionState.Open <> command.Connection.State)) Then
                    Throw New ArgumentNullException("command")
                End If
                command.Parameters.Clear
                command.CommandType = CommandType.StoredProcedure
                command.CommandText = "[dbo].[InsertAddedActivity]"
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@WorkflowInstanceInternalId", internalId))
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@WorkflowInstanceEventId", eventId))
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@QualifiedName", qualifiedName))
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@TypeFullName", typeFullName))
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@AssemblyFullName", assemblyFullName))
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@ParentQualifiedName", parentQualifiedName))
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@AddedActivityAction", addedActivityActionXoml))
                If (-1 = order) Then
                    command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@Order", DBNull.Value))
                Else
                    command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@Order", order))
                End If
                command.ExecuteNonQuery
            End Sub

            Private Sub ExecuteInsertAnnotation(ByVal internalId As Long, ByVal annotations As IList([Of] KeyValuePair([Of] Long, String)), ByVal command As DbCommand)
                If ((Not annotations Is Nothing) AndAlso (annotations.Count > 0)) Then
                    If (annotations.Count > SqlTrackingChannel._dataItemAnnotationBatchSize) Then
                        Throw New ArgumentOutOfRangeException("annotations")
                    End If
                    If (((command Is Nothing) OrElse (command.Connection Is Nothing)) OrElse (ConnectionState.Open <> command.Connection.State)) Then
                        Throw New ArgumentNullException("command")
                    End If
                    command.Parameters.Clear
                    command.CommandType = CommandType.StoredProcedure
                    command.CommandText = "[dbo].[InsertTrackingDataItemAnnotationMultiple]"
                    command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@WorkflowInstanceInternalId", internalId))
                    Dim num As Integer = 1
                    Dim pair As KeyValuePair([Of] Long, String)
                    For Each pair In annotations
                        Dim str As String = num++.ToString(CultureInfo.InvariantCulture)
                        command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter(("@HasData" & str), True))
                        command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter(("@TrackingDataItemId" & str), pair.Key))
                        command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter(("@Annotation" & str), pair.Value))
                    Next
                    command.ExecuteNonQuery
                End If
            End Sub

            Private Sub ExecuteInsertEventAnnotation(ByVal internalId As Long, ByVal eventTypeId As Char, ByVal annotations As IList([Of] KeyValuePair([Of] Long, String)), ByVal command As DbCommand)
                If ((Not annotations Is Nothing) AndAlso (annotations.Count > 0)) Then
                    If (annotations.Count > SqlTrackingChannel._eventAnnotationBatchSize) Then
                        Throw New ArgumentOutOfRangeException("annotations")
                    End If
                    If (((command Is Nothing) OrElse (command.Connection Is Nothing)) OrElse (ConnectionState.Open <> command.Connection.State)) Then
                        Throw New ArgumentNullException("command")
                    End If
                    command.Parameters.Clear
                    command.CommandType = CommandType.StoredProcedure
                    command.CommandText = "[dbo].[InsertEventAnnotationMultiple]"
                    command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@WorkflowInstanceInternalId", internalId))
                    command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@EventTypeId", eventTypeId))
                    Dim num As Integer = 1
                    Dim pair As KeyValuePair([Of] Long, String)
                    For Each pair In annotations
                        Dim str As String = num++.ToString(CultureInfo.InvariantCulture)
                        command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter(("@HasData" & str), True))
                        command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter(("@EventId" & str), pair.Key))
                        command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter(("@Annotation" & str), pair.Value))
                    Next
                    command.ExecuteNonQuery
                End If
            End Sub

            Private Sub ExecuteInsertRemovedActivity(ByVal internalId As Long, ByVal qualifiedName As String, ByVal parentQualifiedName As String, ByVal removedActivityActionXoml As String, ByVal eventId As Long, ByVal order As Integer, ByVal command As DbCommand)
                If (((command Is Nothing) OrElse (command.Connection Is Nothing)) OrElse (ConnectionState.Open <> command.Connection.State)) Then
                    Throw New ArgumentNullException("command")
                End If
                command.Parameters.Clear
                command.CommandType = CommandType.StoredProcedure
                command.CommandText = "[dbo].[InsertRemovedActivity]"
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@WorkflowInstanceInternalId", internalId))
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@WorkflowInstanceEventId", eventId))
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@QualifiedName", qualifiedName))
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@ParentQualifiedName", parentQualifiedName))
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@RemovedActivityAction", removedActivityActionXoml))
                If (-1 = order) Then
                    command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@Order", DBNull.Value))
                Else
                    command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@Order", order))
                End If
                command.ExecuteNonQuery
            End Sub

            Private Sub ExecuteInsertTrackingDataItems(ByVal internalId As Long, ByVal eventTypeId As Char, ByVal items As IList([Of] KeyValuePair([Of] Long, TrackingDataItem)), ByVal command As DbCommand)
                If ((Not items Is Nothing) AndAlso (items.Count > 0)) Then
                    If (items.Count > SqlTrackingChannel._dataItemAnnotationBatchSize) Then
                        Throw New ArgumentOutOfRangeException("items")
                    End If
                    If (((command Is Nothing) OrElse (command.Connection Is Nothing)) OrElse (ConnectionState.Open <> command.Connection.State)) Then
                        Throw New ArgumentException
                    End If
                    command.CommandType = CommandType.StoredProcedure
                    command.CommandText = "[dbo].[InsertTrackingDataItemMultiple]"
                    command.Parameters.Clear
                    command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@WorkflowInstanceInternalId", internalId))
                    command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@EventTypeId", eventTypeId))
                    Dim index As Integer = 1
                    Dim pair As KeyValuePair([Of] Long, TrackingDataItem)
                    For Each pair In items
                        Dim str As String = index++.ToString(CultureInfo.InvariantCulture)
                        Dim item As SerializedDataItem = [TryCast](pair.Value,SerializedDataItem)
                        If (item Is Nothing) Then
                            item = Me.SerializeDataItem(pair.Value)
                        End If
                        Dim type As Type = item.Type
                        command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter(("@EventId" & str), pair.Key))
                        command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter(("@FieldName" & str), item.FieldName))
                        command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter(("@TypeFullName" & str), If((type Is Nothing), Nothing, type.FullName)))
                        command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter(("@AssemblyFullName" & str), If((type Is Nothing), Nothing, type.Assembly.FullName)))
                        command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter(("@Data_Str" & str), item.StringData))
                        command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter(("@Data_Blob" & str), item.SerializedData))
                        command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter(("@DataNonSerializable" & str), item.NonSerializable))
                        command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter(("@TrackingDataItemId" & str), DbType.Int64, ParameterDirection.Output))
                    Next
                    command.ExecuteNonQuery
                    Dim list As New List([Of] Long)(SqlTrackingChannel._dataItemAnnotationBatchSize)
                    index
                    For index = 0 To items.Count - 1
                        Dim str2 As String = (index + 1).ToString(CultureInfo.InvariantCulture)
                        list.Insert(index, CLng(command.Parameters.Item(("@TrackingDataItemId" & str2)).Value))
                    Next index
                    Dim annotations As New List([Of] KeyValuePair([Of] Long, String))(SqlTrackingChannel._dataItemAnnotationBatchSize)
                    index = 0
                    Dim pair2 As KeyValuePair([Of] Long, TrackingDataItem)
                    For Each pair2 In items
                        Dim item2 As TrackingDataItem = pair2.Value
                        Dim key As Long = list.Item(index++)
                        Dim str3 As String
                        For Each str3 In item2.Annotations
                            annotations.Add(New KeyValuePair([Of] Long, String)(key, str3))
                            If (annotations.Count = SqlTrackingChannel._dataItemAnnotationBatchSize) Then
                                Me.ExecuteInsertAnnotation(internalId, annotations, command)
                                annotations.Clear
                            End If
                        Next
                    Next
                    If (annotations.Count > 0) Then
                        Me.ExecuteInsertAnnotation(internalId, annotations, command)
                    End If
                End If
            End Sub

            Private Sub ExecuteInsertUserEvent(ByVal param As Object)
                Dim record As UserTrackingRecord = [TryCast](param,UserTrackingRecord)
                If (record Is Nothing) Then
                    Throw New ArgumentException(ExecutionStringManager.InvalidUserTrackingRecordParameter, "param")
                End If
                Dim connection As DbConnection = Me.DbResourceAllocator.OpenNewConnection
                Dim transaction As DbTransaction = Nothing
                Try 
                    transaction = connection.BeginTransaction(IsolationLevel.ReadCommitted)
                    Dim command As DbCommand = connection.CreateCommand
                    command.Transaction = transaction
                    Me.ExecuteInsertUserEvent(Me._internalId, record, command)
                    transaction.Commit
                Catch exception1 As Exception
                    Try 
                        If (Not transaction Is Nothing) Then
                            transaction.Rollback
                        End If
                    Catch exception2 As Exception
                    End Try
                    Throw
                Finally
                    If ((Not connection Is Nothing) AndAlso (connection.State <> ConnectionState.Closed)) Then
                        connection.Close
                    End If
                End Try
            End Sub

            Private Sub ExecuteInsertUserEvent(ByVal internalId As Long, ByVal record As UserTrackingRecord, ByVal command As DbCommand)
                If (((command Is Nothing) OrElse (command.Connection Is Nothing)) OrElse (ConnectionState.Open <> command.Connection.State)) Then
                    Throw New ArgumentException
                End If
                Dim id As Long = -1
                Dim flag As Boolean = False
                Dim key As String = Me.BuildQualifiedNameVarName(record.QualifiedName, record.ContextGuid, record.ParentContextGuid)
                If Me.TryGetActivityInstanceId(key, id) Then
                    flag = True
                End If
                Me.BuildInsertUserEventParameters(internalId, id, record, command)
                command.ExecuteNonQuery
                If Not flag Then
                    Me.SetActivityInstanceId(key, CLng(command.Parameters.Item("@ActivityInstanceId").Value))
                End If
                Dim num2 As Long = CLng(command.Parameters.Item("@UserEventId").Value)
                Dim annotations As New List([Of] KeyValuePair([Of] Long, String))(10)
                Dim items As New List([Of] KeyValuePair([Of] Long, TrackingDataItem))(10)
                Dim str2 As String
                For Each str2 In record.Annotations
                    annotations.Add(New KeyValuePair([Of] Long, String)(num2, str2))
                Next
                Dim item As TrackingDataItem
                For Each item In record.Body
                    items.Add(New KeyValuePair([Of] Long, TrackingDataItem)(num2, item))
                Next
                Me.BatchExecuteInsertEventAnnotation(internalId, "u"c, annotations, command)
                Me.BatchExecuteInsertTrackingDataItems(internalId, "u"c, items, command)
            End Sub

            Private Sub ExecuteInsertWorkflowChange(ByVal param As Object)
                Dim record As WorkflowTrackingRecord = [TryCast](param,WorkflowTrackingRecord)
                If (record Is Nothing) Then
                    Throw New ArgumentException(ExecutionStringManager.InvalidWorkflowTrackingRecordParameter, "param")
                End If
                Dim command As DbCommand = Me.DbResourceAllocator.NewCommand
                Try 
                    If (ConnectionState.Open <> command.Connection.State) Then
                        command.Connection.Open
                    End If
                    command.Transaction = command.Connection.BeginTransaction
                    Me.ExecuteInsertWorkflowChange(Me._internalId, record, command)
                    command.Transaction.Commit
                Catch exception1 As Exception
                    Try 
                        If ((Not command Is Nothing) AndAlso (Not command.Transaction Is Nothing)) Then
                            command.Transaction.Rollback
                        End If
                    Catch exception2 As Exception
                    End Try
                    Throw
                Finally
                    If (((Not command Is Nothing) AndAlso (Not command.Connection Is Nothing)) AndAlso (command.Connection.State <> ConnectionState.Closed)) Then
                        command.Connection.Close
                    End If
                End Try
            End Sub

            Private Sub ExecuteInsertWorkflowChange(ByVal internalId As Long, ByVal record As WorkflowTrackingRecord, ByVal command As DbCommand)
                If (record Is Nothing) Then
                    Throw New ArgumentNullException("record")
                End If
                If (record.EventArgs Is Nothing) Then
                    Throw New InvalidOperationException(ExecutionStringManager.InvalidWorkflowChangeArgs)
                End If
                If (((command Is Nothing) OrElse (command.Connection Is Nothing)) OrElse (ConnectionState.Open <> command.Connection.State)) Then
                    Throw New ArgumentNullException("command")
                End If
                If Not TypeOf record.EventArgs Is SerializedWorkflowChangedEventArgs Then
                    record = Me.SerializeRecord(record)
                End If
                Me.BuildInsertWorkflowInstanceEventParameters(internalId, record, Nothing, command)
                command.ExecuteNonQuery
                Dim eventId As Long = CLng(command.Parameters.Item("@WorkflowInstanceEventId1").Value)
                Dim eventArgs As SerializedWorkflowChangedEventArgs = DirectCast(record.EventArgs, SerializedWorkflowChangedEventArgs)
                If ((Not eventArgs.AddedActivities Is Nothing) AndAlso (eventArgs.AddedActivities.Count > 0)) Then
                    Dim activity As AddedActivity
                    For Each activity In eventArgs.AddedActivities
                        Me.ExecuteInsertAddedActivity(internalId, activity.QualifiedName, activity.ParentQualifiedName, activity.ActivityTypeFullName, activity.ActivityTypeAssemblyFullName, activity.AddedActivityActionXoml, eventId, activity.Order, command)
                    Next
                End If
                If ((Not eventArgs.RemovedActivities Is Nothing) AndAlso (eventArgs.RemovedActivities.Count > 0)) Then
                    Dim activity2 As RemovedActivity
                    For Each activity2 In eventArgs.RemovedActivities
                        Me.ExecuteInsertRemovedActivity(internalId, activity2.QualifiedName, activity2.ParentQualifiedName, activity2.RemovedActivityActionXoml, eventId, activity2.Order, command)
                    Next
                End If
                Dim annotations As New List([Of] KeyValuePair([Of] Long, String))(record.Annotations.Count)
                Dim str As String
                For Each str In record.Annotations
                    annotations.Add(New KeyValuePair([Of] Long, String)(eventId, str))
                Next
                Me.BatchExecuteInsertEventAnnotation(internalId, "w"c, annotations, command)
            End Sub

            Private Function ExecuteInsertWorkflowInstance(ByVal command As DbCommand) As Long
                Dim num As Long
                If (command Is Nothing) Then
                    Throw New ArgumentNullException("command")
                End If
                If ((command.Connection Is Nothing) OrElse (ConnectionState.Open <> command.Connection.State)) Then
                    Throw New ArgumentException(ExecutionStringManager.InvalidCommandBadConnection, "command")
                End If
                Dim str As String = [TryCast](Me._parameters.RootActivity.GetValue(Activity.WorkflowXamlMarkupProperty),String)
                If ((Not str Is Nothing) AndAlso (str.Length > 0)) Then
                    Me.InsertWorkflow(command, Me._parameters.InstanceId, Nothing, Me._parameters.RootActivity)
                Else
                    Me.InsertWorkflow(command, Me._parameters.InstanceId, Me._parameters.WorkflowType, Me._parameters.RootActivity)
                End If
                Me.BuildInsertWorkflowInstanceParameters(command)
                Dim reader As DbDataReader = Nothing
                Try 
                    reader = command.ExecuteReader
                    If reader.Read Then
                        Me._tmpInternalId = reader.GetInt64(0)
                    End If
                    num = Me._tmpInternalId
                Finally
                    If (Not reader Is Nothing) Then
                        reader.Close
                    End If
                End Try
                Return num
            End Function

            Private Sub ExecuteInsertWorkflowInstance(ByVal param As Object)
                Dim dbConnection As DbConnection = Me.DbResourceAllocator.OpenNewConnection
                Dim command As DbCommand = DbResourceAllocator.NewCommand(dbConnection)
                Dim transaction As DbTransaction = Nothing
                Try 
                    transaction = dbConnection.BeginTransaction(IsolationLevel.ReadCommitted)
                    command.Connection = dbConnection
                    command.Transaction = transaction
                    Me._internalId = Me.ExecuteInsertWorkflowInstance(command)
                    transaction.Commit
                Catch exception1 As Exception
                    Try 
                        If (Not transaction Is Nothing) Then
                            transaction.Rollback
                        End If
                    Catch exception2 As Exception
                    End Try
                    Throw
                Finally
                    If ((Not dbConnection Is Nothing) AndAlso (dbConnection.State <> ConnectionState.Closed)) Then
                        dbConnection.Close
                    End If
                End Try
            End Sub

            Private Sub ExecuteInsertWorkflowInstanceEvent(ByVal param As Object)
                Dim record As WorkflowTrackingRecord = [TryCast](param,WorkflowTrackingRecord)
                If (record Is Nothing) Then
                    Throw New ArgumentException(ExecutionStringManager.InvalidWorkflowTrackingRecordParameter, "param")
                End If
                Dim dbConnection As DbConnection = Me.DbResourceAllocator.OpenNewConnection
                Dim command As DbCommand = DbResourceAllocator.NewCommand(dbConnection)
                Dim transaction As DbTransaction = Nothing
                Try 
                    transaction = dbConnection.BeginTransaction(IsolationLevel.ReadCommitted)
                    command.Connection = dbConnection
                    command.Transaction = transaction
                    Me.ExecuteInsertWorkflowInstanceEvent(Me._internalId, record, Nothing, command)
                    transaction.Commit
                Catch exception1 As Exception
                    Try 
                        If (Not transaction Is Nothing) Then
                            transaction.Rollback
                        End If
                    Catch exception2 As Exception
                    End Try
                    Throw
                Finally
                    If ((Not dbConnection Is Nothing) AndAlso (dbConnection.State <> ConnectionState.Closed)) Then
                        dbConnection.Close
                    End If
                End Try
            End Sub

            Private Sub ExecuteInsertWorkflowInstanceEvent(ByVal internalId As Long, ByVal record1 As WorkflowTrackingRecord, ByVal record2 As WorkflowTrackingRecord, ByVal command As DbCommand)
                If (((command Is Nothing) OrElse (command.Connection Is Nothing)) OrElse (ConnectionState.Open <> command.Connection.State)) Then
                    Throw New ArgumentException
                End If
                Me.BuildInsertWorkflowInstanceEventParameters(internalId, record1, record2, command)
                command.ExecuteNonQuery
                Dim key As Long = CLng(command.Parameters.Item("@WorkflowInstanceEventId1").Value)
                Dim num2 As Long = -1
                If (Not record2 Is Nothing) Then
                    num2 = CLng(command.Parameters.Item("@WorkflowInstanceEventId2").Value)
                End If
                Dim annotations As New List([Of] KeyValuePair([Of] Long, String))((record1.Annotations.Count + If((record2 Is Nothing), 0, record2.Annotations.Count)))
                Dim str As String
                For Each str In record1.Annotations
                    annotations.Add(New KeyValuePair([Of] Long, String)(key, str))
                Next
                If (Not record2 Is Nothing) Then
                    Dim str2 As String
                    For Each str2 In record2.Annotations
                        annotations.Add(New KeyValuePair([Of] Long, String)(num2, str2))
                    Next
                End If
                Me.BatchExecuteInsertEventAnnotation(internalId, "w"c, annotations, command)
            End Sub

            Private Sub ExecuteSetEndDate(ByVal param As Object)
                Dim command As DbCommand = Nothing
                Try 
                    command = DbResourceAllocator.NewCommand(Me.DbResourceAllocator.OpenNewConnection(False))
                    Me.ExecuteSetEndDate(Me._internalId, command)
                Finally
                    If (((Not command Is Nothing) AndAlso (Not command.Connection Is Nothing)) AndAlso (command.Connection.State <> ConnectionState.Closed)) Then
                        command.Connection.Close
                    End If
                End Try
            End Sub

            Private Sub ExecuteSetEndDate(ByVal internalId As Long, ByVal command As DbCommand)
                If (command Is Nothing) Then
                    Throw New ArgumentNullException("command")
                End If
                command.Parameters.Clear
                command.CommandText = "[dbo].[SetWorkflowInstanceEndDateTime]"
                command.CommandType = CommandType.StoredProcedure
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@WorkflowInstanceInternalId", internalId))
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@EndDateTime", DateTime.UtcNow))
                command.ExecuteNonQuery
            End Sub

            Private Function GetActivitiesXml(ByVal root As CompositeActivity) As String
                If (root Is Nothing) Then
                    Return Nothing
                End If
                Dim output As New StringBuilder
                Dim writer As XmlWriter = XmlWriter.Create(output)
                Try 
                    writer.WriteStartDocument
                    writer.WriteStartElement("Activities")
                    Me.WriteActivity(root, writer)
                    writer.WriteEndElement
                    writer.WriteEndDocument
                Finally
                    writer.Flush
                    writer.Close
                End Try
                Return output.ToString
            End Function

            Private Function GetAllEnabledActivities(ByVal compositeActivity As CompositeActivity) As IList([Of] Activity)
                If (compositeActivity Is Nothing) Then
                    Throw New ArgumentNullException("compositeActivity")
                End If
                Dim list As New List([Of] Activity)(compositeActivity.EnabledActivities)
                Dim activity As Activity
                For Each activity In DirectCast(compositeActivity, ISupportAlternateFlow).AlternateFlowActivities
                    If Not list.Contains(activity) Then
                        list.Add(activity)
                    End If
                Next
                Return list
            End Function

            Private Sub GetCallPathKeys(ByVal callPath As IList([Of] String))
                If ((Not callPath Is Nothing) AndAlso (callPath.Count > 0)) Then
                    Dim i As Integer
                    For i = 0 To callPath.Count - 1
                        Me._callPathKey = (Me._callPathKey & "." & callPath.Item(i))
                        If (i < (callPath.Count - 1)) Then
                            Me._parentCallPathKey = (Me._parentCallPathKey & "." & callPath.Item(i))
                        End If
                    Next i
                    If (Not Me._callPathKey Is Nothing) Then
                        Me._callPathKey = Me.SqlEscape(Me._callPathKey.Substring(1))
                    End If
                    If (Not Me._parentCallPathKey Is Nothing) Then
                        Me._parentCallPathKey = Me.SqlEscape(Me._parentCallPathKey.Substring(1))
                    End If
                End If
            End Sub

            Private Function GetSqlDateTimeString(ByVal dateTime As DateTime) As String
                Return String.Concat(New String() { dateTime.Year.ToString(CultureInfo.InvariantCulture), Me.PadToDblDigit(dateTime.Month), Me.PadToDblDigit(dateTime.Day), " ", dateTime.Hour.ToString(CultureInfo.InvariantCulture), ":", dateTime.Minute.ToString(CultureInfo.InvariantCulture), ":", dateTime.Second.ToString(CultureInfo.InvariantCulture), ":", dateTime.Millisecond.ToString(CultureInfo.InvariantCulture) })
            End Function

            Friend Function GetXomlDocument(ByVal obj As Object) As String
                Dim str As String = Nothing
                [Using] writer As StringWriter = New StringWriter(CultureInfo.InvariantCulture)
                    [Using] writer2 As XmlWriter = SqlTrackingService.CreateXmlWriter(writer)
                        New WorkflowMarkupSerializer().Serialize(writer2, obj)
                        str = writer.ToString
                    End [Using]
                End [Using]
                Return str
            End Function

            Private Sub InsertWorkflow(ByVal command As DbCommand, ByVal workflowInstanceId As Guid, ByVal workflowType As Type, ByVal rootActivity As Activity)
                Dim xomlDocument As String = Nothing
                If (Not workflowType Is Nothing) Then
                    SyncLock Me._service._typeCacheLock
                        If Me._service._types.Contains(workflowType.AssemblyQualifiedName) Then
                            Return
                        End If
                        xomlDocument = Me.GetXomlDocument(rootActivity)
                        goto Label_006A
                    End SyncLock
                End If
                SyncLock Me._service._typeCacheLock
                    xomlDocument = Me.GetXomlDocument(rootActivity)
                End SyncLock
            Label_006A:
                command.Parameters.Clear
                command.CommandType = CommandType.StoredProcedure
                command.CommandText = "[dbo].[InsertWorkflow]"
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@TypeFullName", If((workflowType Is Nothing), workflowInstanceId.ToString, workflowType.FullName)))
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@AssemblyFullName", If((workflowType Is Nothing), workflowInstanceId.ToString, workflowType.Assembly.FullName)))
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@IsInstanceType", (workflowType Is Nothing)))
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@WorkflowDefinition", xomlDocument))
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@WorkflowId", DbType.Int32, ParameterDirection.Output))
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@Exists", DbType.Boolean, ParameterDirection.Output))
                command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@Activities", Me.GetActivitiesXml(DirectCast(rootActivity, CompositeActivity))))
                command.ExecuteNonQuery
                If (Not workflowType Is Nothing) Then
                    SyncLock Me._service._typeCacheLock
                        If Not Me._service._types.Contains(workflowType.AssemblyQualifiedName) Then
                            Me._service._types.Add(workflowType)
                        End If
                    End SyncLock
                End If
            End Sub

            Protected Friend Overrides Sub InstanceCompletedOrTerminated()
                If Me._isTrans Then
                    Me._completedTerminated = True
                    If Me._service.PartitionOnCompletion Then
                        Me._pendingArchive = True
                    End If
                Else
                    Me._service.ExecuteRetried(New ExecuteRetriedDelegate(AddressOf Me.ExecuteSetEndDate), Nothing)
                    If Me._service.PartitionOnCompletion Then
                        Me._service.ExecuteRetried(New ExecuteRetriedDelegate(AddressOf Me.PartitionInstance), Nothing)
                    End If
                End If
            End Sub

            Public Function MustCommit(ByVal items As ICollection) As Boolean
                Return False
            End Function

            Private Function PadToDblDigit(ByVal num As Integer) As String
                Dim str As String = num.ToString(CultureInfo.InvariantCulture)
                If (str.Length = 1) Then
                    Return ("0" & str)
                End If
                Return str
            End Function

            Private Sub PartitionInstance(ByVal param As Object)
                Dim command As DbCommand = Nothing
                Try 
                    command = DbResourceAllocator.NewCommand(Me.DbResourceAllocator.OpenNewConnection(False))
                    command.CommandText = "[dbo].[PartitionWorkflowInstance]"
                    command.CommandType = CommandType.StoredProcedure
                    command.Parameters.Add(Me.DbResourceAllocator.NewDbParameter("@WorkflowInstanceInternalId", Me._internalId))
                    command.ExecuteNonQuery
                Finally
                    If (((Not command Is Nothing) AndAlso (Not command.Connection Is Nothing)) AndAlso (command.Connection.State <> ConnectionState.Closed)) Then
                        command.Connection.Close
                    End If
                End Try
            End Sub

            Private Sub RemoveActivityInstanceId(ByVal key As String)
                If (Me._isTrans AndAlso Me._tmpActivityInstanceId.ContainsKey(key)) Then
                    Me._tmpActivityInstanceId.Remove(key)
                End If
                If Me._activityInstanceId.ContainsKey(key) Then
                    Me._activityInstanceId.Remove(key)
                End If
            End Sub

            Protected Friend Overrides Sub Send(ByVal record As TrackingRecord)
                If ((Guid.Empty = Me._parameters.InstanceId) OrElse (record Is Nothing)) Then
                    Throw New ArgumentException(ExecutionStringManager.MissingParametersTrack)
                End If
                If TypeOf record Is ActivityTrackingRecord Then
                    Dim record2 As ActivityTrackingRecord = [TryCast](record,ActivityTrackingRecord)
                    If Me._isTrans Then
                        WorkflowEnvironment.WorkBatch.Add(Me, Me.SerializeRecord(record2))
                    Else
                        Me._service.ExecuteRetried(New ExecuteRetriedDelegate(AddressOf Me.ExecuteInsertActivityStatusInstance), Me.SerializeRecord(record2))
                    End If
                ElseIf TypeOf record Is WorkflowTrackingRecord Then
                    Dim record3 As WorkflowTrackingRecord = DirectCast(record, WorkflowTrackingRecord)
                    If Me._isTrans Then
                        WorkflowEnvironment.WorkBatch.Add(Me, Me.SerializeRecord(record3))
                    ElseIf (TrackingWorkflowEvent.Changed = record3.TrackingWorkflowEvent) Then
                        Me._service.ExecuteRetried(New ExecuteRetriedDelegate(AddressOf Me.ExecuteInsertWorkflowChange), Me.SerializeRecord(record3))
                    Else
                        Me._service.ExecuteRetried(New ExecuteRetriedDelegate(AddressOf Me.ExecuteInsertWorkflowInstanceEvent), Me.SerializeRecord(record3))
                    End If
                ElseIf TypeOf record Is UserTrackingRecord Then
                    Dim record4 As UserTrackingRecord = DirectCast(record, UserTrackingRecord)
                    If Me._isTrans Then
                        WorkflowEnvironment.WorkBatch.Add(Me, Me.SerializeRecord(record4))
                    Else
                        Me._service.ExecuteRetried(New ExecuteRetriedDelegate(AddressOf Me.ExecuteInsertUserEvent), Me.SerializeRecord(record4))
                    End If
                End If
            End Sub

            Private Function SerializeDataItem(ByVal item As TrackingDataItem) As SerializedDataItem
                If (item Is Nothing) Then
                    Return Nothing
                End If
                Dim item2 As New SerializedDataItem { _
                    .Data = item.Data _
                }
                item2.Annotations.AddRange(item.Annotations)
                item2.FieldName = item.FieldName
                If (Not item.Data Is Nothing) Then
                    Dim flag As Boolean
                    Dim state As Byte() = Nothing
                    Me.SerializeDataItem(item.Data, state, flag)
                    item2.SerializedData = state
                    item2.StringData = item.Data.ToString
                    item2.Type = item.Data.GetType
                    item2.NonSerializable = flag
                End If
                Return item2
            End Function

            Private Sub SerializeDataItem(ByVal data As Object, <Out> ByRef state As Byte(), <Out> ByRef nonSerializable As Boolean)
                nonSerializable = False
                state = Nothing
                If (Not data Is Nothing) Then
                    Dim serializationStream As New MemoryStream(&H400)
                    Dim formatter As New BinaryFormatter
                    Try 
                        formatter.Serialize(serializationStream, data)
                        state = New Byte(serializationStream.Length  - 1) {}
                        serializationStream.Position = 0
                        If (serializationStream.Length <= &H7FFFFFFF) Then
                            Dim num As Integer = 0
                            Dim offset As Integer = 0
                            Dim count As Integer = 0
                            Do
                                offset = (offset + num)
                                count = (CInt(serializationStream.Length) - offset)
                                num = serializationStream.Read(state, offset, count)
                            Loop While (num > 0)
                        End If
                    Catch exception1 As SerializationException
                        nonSerializable = True
                    Finally
                        serializationStream.Close
                    End Try
                End If
            End Sub

            Private Function SerializeRecord(ByVal record As ActivityTrackingRecord) As ActivityTrackingRecord
                If ((Not record.Body Is Nothing) AndAlso (record.Body.Count <> 0)) Then
                    Dim i As Integer
                    For i = 0 To record.Body.Count - 1
                        record.Body.Item(i) = Me.SerializeDataItem(record.Body.Item(i))
                    Next i
                End If
                Return record
            End Function

            Private Function SerializeRecord(ByVal record As UserTrackingRecord) As UserTrackingRecord
                If (((Not record.Body Is Nothing) AndAlso (record.Body.Count <> 0)) OrElse ((Not record.EventArgs Is Nothing) OrElse (Not record.UserData Is Nothing))) Then
                    If (Not record.UserData Is Nothing) Then
                        Dim flag As Boolean
                        Dim item As New SerializedDataItem
                        Dim state As Byte() = Nothing
                        Me.SerializeDataItem(record.UserData, state, flag)
                        item.Type = record.UserData.GetType
                        item.StringData = record.UserData.ToString
                        item.SerializedData = state
                        item.NonSerializable = flag
                        record.UserData = item
                    End If
                    Dim i As Integer
                    For i = 0 To record.Body.Count - 1
                        record.Body.Item(i) = Me.SerializeDataItem(record.Body.Item(i))
                    Next i
                End If
                Return record
            End Function

            Private Function SerializeRecord(ByVal record As WorkflowTrackingRecord) As WorkflowTrackingRecord
                Dim args As SerializedEventArgs
                If (record.EventArgs Is Nothing) Then
                    Return record
                End If
                If (TrackingWorkflowEvent.Changed = record.TrackingWorkflowEvent) Then
                    Dim args2 As New SerializedWorkflowChangedEventArgs
                    Dim eventArgs As TrackingWorkflowChangedEventArgs = DirectCast(record.EventArgs, TrackingWorkflowChangedEventArgs)
                    If (Not eventArgs Is Nothing) Then
                        Dim i As Integer
                        For i = 0 To eventArgs.Changes.Count - 1
                            Dim action As WorkflowChangeAction = eventArgs.Changes.Item(i)
                            If TypeOf action Is RemovedActivityAction Then
                                Me.AddRemovedActivity(DirectCast(action, RemovedActivityAction), i, args2.RemovedActivities)
                            ElseIf TypeOf action Is AddedActivityAction Then
                                Me.AddAddedActivity(DirectCast(action, AddedActivityAction), i, args2.AddedActivities)
                            End If
                        Next i
                    End If
                    args = args2
                Else
                    Dim flag As Boolean
                    args = New SerializedEventArgs
                    Dim state As Byte() = Nothing
                    Me.SerializeDataItem(record.EventArgs, state, flag)
                    args.SerializedArgs = state
                    If flag Then
                        Dim exception As Exception
                        Select Case record.TrackingWorkflowEvent
                            Case TrackingWorkflowEvent.Exception
                                exception = DirectCast(record.EventArgs, TrackingWorkflowExceptionEventArgs).Exception
                                If (Not exception Is Nothing) Then
                                    Me.SerializeDataItem(exception.ToString, state, flag)
                                    args.SerializedArgs = state
                                End If
                                goto Label_0130
                            Case TrackingWorkflowEvent.Terminated
                                exception = DirectCast(record.EventArgs, TrackingWorkflowTerminatedEventArgs).Exception
                                If (Not exception Is Nothing) Then
                                    Me.SerializeDataItem(exception.ToString, state, flag)
                                    args.SerializedArgs = state
                                End If
                                goto Label_0130
                        End Select
                    End If
                End If
            Label_0130:
                args.Type = record.EventArgs.GetType
                record.EventArgs = args
                Return record
            End Function

            Private Sub SetActivityInstanceId(ByVal key As String, ByVal id As Long)
                If Me._isTrans Then
                    If Not Me._tmpActivityInstanceId.ContainsKey(key) Then
                        Me._tmpActivityInstanceId.Add(key, id)
                    End If
                ElseIf Not Me._activityInstanceId.ContainsKey(key) Then
                    Me._activityInstanceId.Add(key, id)
                End If
            End Sub

            Private Function SqlEscape(ByVal val As String) As String
                If (val Is Nothing) Then
                    Return Nothing
                End If
                Return val.Replace("'", "''")
            End Function

            Private Function TryGetActivityInstanceId(ByVal key As String, <Out> ByRef id As Long) As Boolean
                Return (Me._activityInstanceId.TryGetValue(key, id) OrElse (Me._isTrans AndAlso Me._tmpActivityInstanceId.TryGetValue(key, id)))
            End Function

            Private Sub WriteActivity(ByVal activity As Activity, ByVal writer As XmlWriter)
                If (Not activity Is Nothing) Then
                    If (writer Is Nothing) Then
                        Throw New ArgumentNullException("writer")
                    End If
                    Dim type As Type = activity.GetType
                    writer.WriteStartElement("Activity")
                    writer.WriteElementString("TypeFullName", type.FullName)
                    writer.WriteElementString("AssemblyFullName", type.Assembly.FullName)
                    writer.WriteElementString("QualifiedName", activity.QualifiedName)
                    If (Not activity.Parent Is Nothing) Then
                        writer.WriteElementString("ParentQualifiedName", activity.Parent.QualifiedName)
                    End If
                    writer.WriteEndElement
                    If TypeOf activity Is CompositeActivity Then
                        Dim activity2 As Activity
                        For Each activity2 In Me.GetAllEnabledActivities(DirectCast(activity, CompositeActivity))
                            Me.WriteActivity(activity2, writer)
                        Next
                    End If
                End If
            End Sub


            ' Properties
            Private ReadOnly Property DbResourceAllocator As DbResourceAllocator
                Get
                    Return Me._service.DbResourceAllocator
                End Get
            End Property

            Private ReadOnly Property WorkflowCommitWorkBatchService As WorkflowCommitWorkBatchService
                Get
                    Return Me._service._transactionService
                End Get
            End Property


            ' Fields
            Private Shared _activityEventBatchSize As Integer = 5
            Private _activityInstanceId As Dictionary([Of] String, Long)
            Private _callPathKey As String
            Private _completedTerminated As Boolean
            Private Shared _dataItemAnnotationBatchSize As Integer = 5
            Private Shared _dataItemBatchSize As Integer = 5
            Private Shared _eventAnnotationBatchSize As Integer = 5
            Private _internalId As Long
            Private _isTrans As Boolean
            Private _parameters As TrackingParameters
            Private _parentCallPathKey As String
            Private _pendingArchive As Boolean
            Private _service As SqlTrackingService
            Private _tmpActivityInstanceId As Dictionary([Of] String, Long)
            Private _tmpInternalId As Long
        End Class

        Private Class TypeKeyedCollection
            Inherits KeyedCollection([Of] String, Type)
            ' Methods
            Protected Overrides Function GetKeyForItem(ByVal item As Type) As String
                Return item.AssemblyQualifiedName
            End Function

        End Class
    End Class
End Namespace

